﻿// See https://aka.ms/new-console-template for more information
//程序编译会生成exe/dll文件 里面会包含matedata（元数据，数据清单）里面会包含但钱程序集中有哪些元素成员
//List<>
//IL中间语言--也是一个标准的面向对象语言
//ILSpy--反编译工具，可以把dll/exe通过反编译呈现出源码状态
//反射就是一个微软提供的来自于Rflection命名空间的一个帮助类库，可以去解析并使用matedata元数据

//动态加载dll文件

using Business.DB.Interface;
using System.Reflection;
using 反射;

Assembly assembly1 = Assembly.LoadFrom("Business.DB.Sqlserver.dll");//当前执行目录下去读取dll文件

//Assembly assembly2 = Assembly.LoadFile("D:\\backend\\zhaoxiTest\\Business.DB.Sqlserver\\bin\\Debug\\net8.0\\Business.DB.Sqlserver.dll");//全路径读取

Assembly assembly3 = Assembly.Load("Business.DB.Sqlserver");//不用加上dll后缀，在当前执行的目录下读取

foreach (var item in assembly3.GetTypes())
{
}

//获取类型的名称
Type type = assembly1.GetType("Business.DB.Sqlserver.SqlserverHelper");//使用命名空间全名称

//反射创建对象
//object? oInstance = Activator.CreateInstance(type);
//var oInstance = (SqlserverHelper)Activator.CreateInstance(type);
//dynamic oInstance= Activator.CreateInstance(type);
//oInstance.Query();
//c#是强类型语言，在编译时决定类型，编译器认为这个oInstace是object类型，其实运行时，类型是sqlserverHelper

//动态类型--可以避开编译器的检查
//dynamic oInstance= Activator.CreateInstance(type);
//oInstance.Query();

//var oInstance = Activator.CreateInstance(type) as IDBHelper;
//oInstance.Query();

var oInstance = Activator.CreateInstance(type);

//接口 依赖于抽象
IDBHelper dbHlepr = SimpleFactory.CreateInstance();
dbHlepr.Query();

//反射破坏单例
//Singleton singleton = new();//报错
Singleton singleton = Singleton.GetInstance();
Assembly assembly4 = Assembly.LoadFrom("反射.dll");
Type type1 = assembly4.GetType("反射.Singleton");
object oInstanc2 = Activator.CreateInstance(type1, true);//第二个true表示可以访问私有成员，可以打破访问修饰符的界限

//执行指定构造函数 如果要执行指定构造函数，直接传入和参数列表匹配的数据即可
Type type2 = assembly4.GetType("反射.ReflectionTest");
var oInstance0 = Activator.CreateInstance(type2);
var oInstance1 = Activator.CreateInstance(type2, new object[] { 1 });
var oInstance2 = Activator.CreateInstance(type2, new object[] { "1" });
var oInstance3 = Activator.CreateInstance(type2, new object[] { 1, "1" });

//反射调用方法
//普通方法
MethodInfo method = type2.GetMethod("Show0");
method.Invoke(oInstance0, null);
//重载方法
MethodInfo method1 = type2.GetMethod("Show", new Type[] { typeof(int) });
method1.Invoke(oInstance0, new object[] { 1 });
MethodInfo method2 = type2.GetMethod("Show", new Type[] { typeof(string) });
method2.Invoke(oInstance0, new object[] { "1" });

//此处为何要这么写？
//因为在程序集中的show方法重载中存在参数相同，其中一个有泛型参数，其中一个没有的情况，因此需要特殊指定
MethodInfo method3 = type2.GetMethods().Where(x => x.Name == "Show" && !x.IsGenericMethod && x.GetParameters().Length == 2 && x.GetParameters()[0].ParameterType == typeof(int) && x.GetParameters()[1].ParameterType == typeof(string)).FirstOrDefault();
method3.Invoke(oInstance0, new object[] { 1, "1" });

//这种写法与上面的效果相同，getmethod重载方法中第二个参数便是指定泛型参数的个数
MethodInfo method3_2 = type2.GetMethod("Show", 0, new Type[] { typeof(int), typeof(string) });
method3_2.Invoke(oInstance0, new object[] { 1, "1" });
//泛型方法

//Type type3 = assembly1.GetType("反射.ReflectionTest`0"); 如果是泛型类，便需要在命名空间之后加上 “ ` ”符号 再加上泛型参数的个数
//MethodInfo method4 = type3.GetMethod("Show", new Type[] { typeof(int), typeof(string) }).MakeGenericMethod(new Type[] { typeof(int) });
//method4.Invoke(oInstance0,new object[] { 1,"1"});

//静态方法
MethodInfo method5 = type2.GetMethod("Show5");
method5.Invoke(null, new object[] { });

//反射的多种应用场景
//1.在MVC中有应用，请求的路径包含了控制器和方法，通过反射获取控制器的类型，创建实例，根据路径中的方法的名称确定要执行的具体Action 方法
//2.简单工厂其实是一个IOC容器的雏形~~
//3.反射在ORM框架中的使用
//4。开发中无处不在！

{
    //反射调用属性字段
    Type type5 = typeof(People);
    object oInstance5 = Activator.CreateInstance(type5);
    foreach (var prop in type5.GetProperties())
    {
        if (prop.PropertyType == typeof(int))
        {
            prop.SetValue(oInstance5, 1);
        }
        if (prop.PropertyType == typeof(string))
        {
            prop.SetValue(oInstance5, "1");
        }

        Console.WriteLine($"属性:{prop.Name},值:{prop.GetValue(oInstance5)}");
    }

    //字段
    //foreach (var filed in type5.GetFields())
    //{
    //    if (filed.FieldType == typeof(int))
    //    {
    //        filed.SetValue(oInstance5, 1);
    //    }
    //    if (filed.FieldType == typeof(string))
    //    {
    //        filed.SetValue(oInstance5, "1");
    //    }

    //    Console.WriteLine($"属性:{filed.Name},值:{filed.GetValue(oInstance5)}");
    //}
}

Console.WriteLine("Hello, World!");